#pragma once
#ifndef __LIT__DISPLAY__OBJECT__HH__
#define __LIT__DISPLAY__OBJECT__HH__

#include <string>
#include <tinyxml.h>
#include <LitPrerequisites.h>
#include <LitVector.hpp>
#include <LitExceptions.h>
#include <LitMovableTypes.h>
#include <LitMovableDatas.h>
#include <LitMovableListener.h>

namespace Lit
{
	class LIT_API Movable
	{
	protected:
		std::string				mName;
		OgreSceneNodePtr		mNode;
		OgreSceneManagerPtr		mMgr;
		Ogre::MovableObject*	mObject;
		MovableDatas			mDatas;
		bool					mCreated;

		MovableType				mType;

		std::vector<MovableListener*> mListeners;
	public:
		Movable(MovableType type=MT_UNDEFINED, const std::string &name="");
		Movable( const Movable& rk );
		virtual ~Movable( );
		
		MovableDatas& getDatas();
		const MovableDatas& getDatas() const;

		std::vector<MovableListener*>& getListeners();
		const std::vector<MovableListener*>& getListeners() const;

		void addListener( MovableListener * l );
		bool hasListener( MovableListener * l );
		void removeListener( MovableListener * l );

		Ogre::MovableObject*	getMovable();
		const Ogre::MovableObject*	getMovable() const;		
		void _setMovable( Ogre::MovableObject * obj );

		std::string getMovableTypeStr() const;
		MovableType getMovableType() const;
		void setMovableType( MovableType t );
		
		virtual void create(OgreSceneManagerPtr mgr) = 0;
		virtual void destroy() = 0;

		void setPosition( const Ogre::Vector3 &pos );
		void setOrientation( const Ogre::Quaternion &q );
		void setScale( const Ogre::Vector3 &s );
		
		Ogre::Vector3 getPosition( ) const;
		Ogre::Quaternion getOrientation( ) const;
		Ogre::Vector3 getScale( ) const;
		
		Ogre::AxisAlignedBox	getBoundingBox() const;
		Ogre::Vector3			getSize() const;

		bool hasData( const std::string &name ) const;
		
		template<typename T> void setData( const std::string &name, T& val ){ mDatas.setData<T>( name, val ); }
		template<typename T> void setData( const std::string &name, const T& val ){ mDatas.setData<T>( name, val ); }
		template<typename T> void setData( const std::string &name, T* val ){ mDatas.setData<T>( name, val ); }
		template<typename T> void setData( const std::string &name, const T* val ){ mDatas.setData<T>( name, val ); }

		template<typename T> T getData( const std::string &name, const T& default_val = T(), bool except = false) const{return mDatas.getData<T>( name, default_val, except );}
		template<typename T> T* getData( const std::string &name, T* default_val = NULL, bool except = false ){return mDatas.getData<T>( name, default_val, except );}
		template<typename T> const T* getData( const std::string &name, const T* default_val = NULL, bool except = false ) const{return mDatas.getData<T>( name, default_val, except );}

		const OgreSceneManagerPtr& getSceneManager() const;
		std::string getName() const;

		const OgreSceneNodePtr getNode() const;

		void setCreated( bool c );
		bool isCreated() const;
		
		virtual void exportAttribs( TiXmlElement * elem )=0;
		virtual void importAttribs( TiXmlElement * elem )=0;

	};
	
	typedef RefPtr<Movable>						MovablePtr;
	typedef Vector<MovablePtr>					MovablePtrList;
};

#endif